export interface NormalAIInterface {
    ROWS: number;
    COLS: number;
    player: number;
    player1Win: number[];
    player2Win: number[];
    wins: Array<Array<Array<boolean>>>;
    count: number;
}

export enum PlayerType {
    player1 = 1,
    player2 = 2,
}

export class NormalAI {
    /**
     * 所有赢法数组
     */
    wins: Array<Array<Array<boolean>>> = [];
    /**
     * 赢法数组的长度
     */
    count: number = 0;
    /**
     * 计算机在某个落子的位置上，横向、竖向和斜向上获胜的赢法数量
     * 「赢法」就是指五子棋棋盘上能够获胜的全部局面构成的集合。在五子棋游戏中，赢法有很多种，
     * 其中一种赢法就是横向连成五子的赢法，另一种赢法则是竖向连成五子的赢法，还有一种是斜向连成五子的赢法
     */
    comWin: number[] = [];
    /**
     * 对手在某个落子的位置上，横向、竖向和斜向上获胜的赢法数量
     */
    enemyWin: number[] = [];
    /**
     * 棋盘长度
     */
    ROWS: number = 15;
    /**
     * 棋盘宽度
     */
    COLS: number = 15;
    /**
     * AI标识，标识AI的区分
     */
    player: PlayerType;
    /**
     * 走了多少步
     */
    step: number;

    constructor({ ROWS, COLS, player, player1Win, player2Win, wins, count }: NormalAIInterface) {
        this.wins = wins;
        this.count = count;
        this.ROWS = ROWS;
        this.COLS = COLS;
        this.player = player;
        this.step = 0;
        if (this.player === PlayerType.player1) {
            this.enemyWin = player2Win;
            this.comWin = player1Win;
        } else {
            this.enemyWin = player1Win;
            this.comWin = player2Win;
        }
    }

    /**
     * 计算机思考
     * @param chessBoard 棋盘布局
     * @returns x坐标和y坐标
     */
    computerAI(chessBoard: number[][]): { u: number; v: number } {
        if (this.step === 0 && chessBoard[7][7] === 0) {
            return { u: 7, v: 7 };
        }
        this.step++;
        let enemyScore: number[][] = []; //记录我方得分
        let comScore: number[][] = []; //计录计算机的得分
        let max = 0; //记录最高分
        let u = 0,
            v = 0; //记录最高分位置

        // 初始每个点的分数
        enemyScore = new Array(this.ROWS).fill(0).map(() => new Array(this.COLS).fill(0));
        comScore = new Array(this.ROWS).fill(0).map(() => new Array(this.COLS).fill(0));
        for (let i = 0; i < this.ROWS; ++i) {
            for (let j = 0; j < this.COLS; ++j) {
                // 该点为空点，可以下棋
                if (chessBoard[i][j] === 0) {
                    for (let k = 0; k < this.count; ++k) {
                        // 该点存在某一个赢法
                        if (this.wins[i][j][k]) {
                            // 如果对手在该点存在的赢法数量等于1，记录该点的分数值
                            if (this.enemyWin[k] == 1) {
                                enemyScore[i][j] += 200;
                            } else if (this.enemyWin[k] == 2) {
                                enemyScore[i][j] += 400;
                            } else if (this.enemyWin[k] == 3) {
                                enemyScore[i][j] += 2000;
                            } else if (this.enemyWin[k] == 4) {
                                enemyScore[i][j] += 10000;
                            }
                            // 如果我方在该点存在的赢法数量等于1，记录该点的分数值
                            if (this.comWin[k] == 1) {
                                comScore[i][j] += 220;
                            } else if (this.comWin[k] == 2) {
                                comScore[i][j] += 420;
                            } else if (this.comWin[k] == 3) {
                                comScore[i][j] += 2100;
                            } else if (this.comWin[k] == 4) {
                                comScore[i][j] += 20000;
                            }
                        }
                    }
                    // 先判断对手在该点的最大分数
                    if (enemyScore[i][j] > max) {
                        max = enemyScore[i][j];
                        u = i;
                        v = j;
                    } else if (enemyScore[i][j] == max) {
                        if (comScore[i][j] > comScore[u][v]) {
                            u = i;
                            v = j;
                        }
                    }
                    // 再判断电脑在该点的分数是否大于对手
                    if (comScore[i][j] > max) {
                        max = comScore[i][j];
                        u = i;
                        v = j;
                    } else if (comScore[i][j] == max) {
                        if (enemyScore[i][j] > enemyScore[u][v]) {
                            u = i;
                            v = j;
                        }
                    }
                }
            }
        }
        return { u, v };
    }
}
